// Overlay.cpp: Implementierungsdatei
//

#include "stdafx.h"
#include "Charplan.h"
#include "Overlay.h"


// COverlay

IMPLEMENT_DYNAMIC(COverlay, CWnd)

COverlay::COverlay()
{

}

COverlay::~COverlay()
{
}


BEGIN_MESSAGE_MAP(COverlay, CWnd)
    ON_WM_ERASEBKGND()
    ON_WM_PAINT()
    ON_WM_NCHITTEST()
    ON_WM_TIMER()
END_MESSAGE_MAP()


typedef DWORD (WINAPI *PSLWA)(HWND, DWORD, BYTE, DWORD);
//#define LWA_COLORKEY 1
//#define LWA_ALPHA 2

void COverlay::Create(CWnd* pw, DWORD eff)
{
    if (m_hWnd!=NULL) return;

    mdw_effect = eff;

    // M.Jurkait [7/13/2006]
    // -------------------------
    // Get SetLayeredWindowAttributes
    // -------------------------
    PSLWA pSetLayeredWindowAttributes;
    HMODULE hDLL = LoadLibrary(_T("user32"));
    pSetLayeredWindowAttributes = (PSLWA) GetProcAddress(hDLL,"SetLayeredWindowAttributes");
    if (pSetLayeredWindowAttributes == NULL) return;



    CRect r;
    pw->GetWindowRect(r);

    clear_color.CreateSolidBrush(RGB(255,0,255));
    CString csWndClass = AfxRegisterWndClass(0,0,clear_color);

    //WS_EX_LAYERED
    if (!(CreateEx(0x00080000 /*|WS_EX_TRANSPARENT*/,
                   (LPCTSTR)csWndClass,
                   _T(""),
                   WS_VISIBLE|WS_POPUP,
                   r, pw, NULL)))
    {
        return;
    }


    pSetLayeredWindowAttributes(m_hWnd, RGB(255,0,255), 128, LWA_COLORKEY/*|LWA_ALPHA*/);

    bool b_need_timer = false;
    if (mdw_effect&OVERLAY_SNOW) { InitSnow(); b_need_timer = true; }
    if (mdw_effect&OVERLAY_SANTA) { InitSanta(); b_need_timer = true; }


    if (b_need_timer) SetTimer(1212,100,NULL);

}




void COverlay::SetSize(int x, int y)
{
    if (m_hWnd)  SetWindowPos(NULL,0,0,x,y,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}

void COverlay::SetPos(int x, int y)
{
    if (m_hWnd)  SetWindowPos(NULL,x,y,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}



LRESULT COverlay::OnNcHitTest(CPoint point)
{
    return HTTRANSPARENT;
}



BOOL COverlay::OnEraseBkgnd(CDC* pDC)
{
    return CWnd::OnEraseBkgnd(pDC);
}


void COverlay::OnTimer(UINT_PTR nIDEvent)
{
    Invalidate();
    CWnd::OnTimer(nIDEvent);
}


const int direction[17][2]=
{
    {-1,1},
    {1,1},
    {1,1}, {1,0},{1,0},
    {1,1}, {1,0},{1,0},{1,0},
    {1,1},
    {-1,1},
    {-1,1}, {-1,0},{-1,0},
    {-1,1}, {-1,0},{-1,0}
};


void COverlay::OnPaint()
{
    CPaintDC dc(this);


    CRect r;
    GetClientRect(r);

    CPoint mouse;
    GetCursorPos(&mouse);
    ScreenToClient(&mouse);



    if (mdw_effect&OVERLAY_SANTA) { UpdateSanta(&dc,r,mouse); }
    if (mdw_effect&OVERLAY_SNOW) { UpdateSnow(&dc,r,mouse); }
}




void COverlay::InitSnow()
{
    mc_bitmap_snow.LoadBitmap(IDB_EFF1);
}


void COverlay::UpdateSnow(CDC* dc, const CRect r, const CPoint& mouse)
{
    for (int t=0;t<m_s_postion.GetCount();t++)
    {
        m_s_direction[t].x = (m_s_direction[t].x+1)%17;
        m_s_postion[t] += CPoint(direction[m_s_direction[t].x][0],direction[m_s_direction[t].x][1]);
        if (m_s_direction[t].y>rand()%7)
            m_s_postion[t] += CPoint(direction[m_s_direction[t].x][0],direction[m_s_direction[t].x][1]);

        if (m_s_postion[t].y>r.bottom)
        {
            m_s_postion.RemoveAt(t);
            m_s_direction.RemoveAt(t);
            t--;
        }
        else
        {
            CPoint p = m_s_postion[t] - mouse;
            int dist = p.x*p.x+p.y*p.y;
            if (dist<20*20)
            {
                float fac = 20.0f/(float)dist;
                p.x *= (int)((float)(p.x)*fac);
                p.y *= (int)((float)(p.y)*fac);
                m_s_postion[t] += p;
            }
        }
    }

    if (m_s_postion.GetCount()<100 && (rand()%100)>95)
    {
        m_s_postion.Add(CPoint(rand()%r.Width(),-7));
        m_s_direction.Add(CPoint(rand()%17,rand()%10));
    }


    CDC memdc;
    memdc.CreateCompatibleDC(dc);
    memdc.SelectObject(mc_bitmap_snow);

    for (int t=0;t<m_s_postion.GetCount();t++)
    {
        dc->BitBlt(m_s_postion[t].x,m_s_postion[t].y,8,8,&memdc,0,0,SRCCOPY);
    }
}






void COverlay::InitSanta()
{
    mn_pos = -1;
    mn_frame = -1;
    mn_type = -1;

    mc_bitmap_rudolph.LoadBitmap(IDB_EFF2A);
    mc_bitmap_santa1.LoadBitmap(IDB_EFF2B);
    mc_bitmap_santa2.LoadBitmap(IDB_EFF2C);


    // create mask of rudolph
    CDC copydc,copydc2;
    copydc.CreateCompatibleDC(NULL);
    copydc2.CreateCompatibleDC(NULL);

    mc_bitmap_rudolph_mask.CreateBitmap(97,200,1,1,NULL);

    copydc.SelectObject(mc_bitmap_rudolph);
    copydc2.SelectObject(mc_bitmap_rudolph_mask);

    copydc.SetBkColor(RGB(255,0,255));
    copydc2.BitBlt(0,0,97,200,&copydc,0,0,SRCCOPY);

}


int santa_move[8]={12,12,12,12,7,7,10,11};
int santa_fall[7]={ 1,2,4,7,11,15,19};
int santa_anim[18]={0,1,2,3,4,3,3,3,3,3,3,5,6,7,8,9,10,11};

void COverlay::UpdateSanta(CDC* dc, const CRect r, const CPoint& mouse)
{
    if (mn_frame< 0)
    {
        if ((rand()%1000)> 980)
        {
            mn_frame = 0;
            mn_pos = r.Width();
            mn_santa_pos = mn_pos + 64;

            if (mn_type!=0 || ((rand()%10)>6))
                mn_type = (mn_type+1)%7;

            mn_posy = 0;
            if ((rand()%10)>5)
            {
                mn_posy = r.bottom-100;
            }
            if ((rand()%10)>6)
                mn_posy = rand()%(r.bottom-50);



            switch (mn_type)
            {
                case 0:
                    mn_santa_pos = mn_pos + 64;
                    break;
                case 1:
                    mn_santa_pos = mn_pos + 64;
                    break;
                case 5:
                    mn_santa_pos = mn_pos + 128;
                    break;
                case 6:
                    mn_santa_pos = mn_pos + 64+r.Width()/10;
                    break;
                default:
                    ASSERT(false);
            }
        }
        return;
    }

    // move sledg
    mn_pos-=10;
    mn_frame++;

    if (mn_pos < -100 && mn_santa_pos < -32)
    {
        if (mn_type==7) mn_type = -1;
        mn_frame = -1;
        return;
    }



    int pic = (mn_frame/2)%4;

    CDC memdc;
    memdc.CreateCompatibleDC(dc);

    switch (mn_type)
    {
        case 0:  // nrl
        case 1:  // before - fall
        case 7:  // after catch up
            mn_santa_pos -= 10;
            memdc.SelectObject(mc_bitmap_santa1);
            dc->BitBlt(mn_santa_pos,mn_posy+santa_move[mn_frame%8],29,31,&memdc,29*pic,0,SRCCOPY);

            if (mn_type == 1 && mn_pos<r.Width()*2/3 && pic==2)
            {
                mn_type = 2;
                mn_frame2=0;
            }
            break;


        case 2:  // fall
            mn_santa_pos -= 6;
            memdc.SelectObject(mc_bitmap_santa1);
            dc->BitBlt(mn_santa_pos,mn_posy+santa_fall[mn_frame2],29,32,&memdc,29*2,0,SRCCOPY);
            mn_frame2++;
            if (mn_frame2>6)
            {
                mn_type = 3;
                mn_frame2=0;
            }
            break;

        case 3:  // fall-standup-anim
            memdc.SelectObject(mc_bitmap_santa2);
            dc->BitBlt(mn_santa_pos-50,mn_posy+19,89,31,&memdc,0,31*santa_anim[mn_frame2],SRCCOPY);
            mn_frame2++;
            if (mn_frame2>17)
            {
                mn_type = 4;
                mn_frame2=0;
                mn_santa_pos += 40;
            }
            break;


        case 4:  // run behind - after fall
        case 5:  // run behind
            mn_santa_pos -= 10;
            memdc.SelectObject(mc_bitmap_santa1);
            dc->BitBlt(mn_santa_pos,mn_posy+18,29,32,&memdc,29*((mn_frame/2)%2),32,SRCCOPY);
            break;

        case 6:  // run behind - catch up
            mn_santa_pos -= 12;
            memdc.SelectObject(mc_bitmap_santa1);
            dc->BitBlt(mn_santa_pos,mn_posy+18,29,32,&memdc,29*((mn_frame/2)%2),32,SRCCOPY);

            if (mn_santa_pos <= mn_pos+64)
            {
                mn_type = 7;
                mn_frame = 4;
            }

            break;
    }


    // color-clip-copy
    if (mn_pos > -100)
    {
        memdc.SelectObject(mc_bitmap_rudolph);
        dc->BitBlt(mn_pos,mn_posy,97,50,&memdc,0,50*pic,SRCINVERT);
        memdc.SelectObject(mc_bitmap_rudolph_mask);
        dc->BitBlt(mn_pos,mn_posy,97,50,&memdc,0,50*pic,SRCAND);
        memdc.SelectObject(mc_bitmap_rudolph);
        dc->BitBlt(mn_pos,mn_posy,97,50,&memdc,0,50*pic,SRCINVERT);
    }

}
